package de.szut.ita13sommerfeld.blockadventure.controller;

import java.awt.Graphics;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.Random;

import de.szut.ita13sommerfeld.blockadventure.gameentities.Block;
import de.szut.ita13sommerfeld.blockadventure.gameentities.Entity;
import de.szut.ita13sommerfeld.blockadventure.gameentities.Item;
import de.szut.ita13sommerfeld.blockadventure.gameentities.Missile;
import de.szut.ita13sommerfeld.blockadventure.gameentities.blocks.Bound;
import de.szut.ita13sommerfeld.blockadventure.gameentities.blocks.CheckPoint;
import de.szut.ita13sommerfeld.blockadventure.gameentities.blocks.CoinBox;
import de.szut.ita13sommerfeld.blockadventure.gameentities.blocks.Dirt;
import de.szut.ita13sommerfeld.blockadventure.gameentities.blocks.Grass;
import de.szut.ita13sommerfeld.blockadventure.gameentities.blocks.MissileLauncher;
import de.szut.ita13sommerfeld.blockadventure.gameentities.blocks.Sand;
import de.szut.ita13sommerfeld.blockadventure.gameentities.character.Character;
import de.szut.ita13sommerfeld.blockadventure.gameentities.items.Coin;
import de.szut.ita13sommerfeld.blockadventure.level.SpawnPoint;
import de.szut.ita13sommerfeld.blockadventure.window.Game;
import de.szut.ita13sommerfeld.blockadventure.window.GameCamera;

public class Controller {

	public static enum EntityList {
		ADD, REMOVE;
	}
	
	public LinkedList<Entity> entities = new LinkedList<Entity>();
	private ArrayList<Entity> entitiesToRemove = new ArrayList<Entity>();
	private ArrayList<Entity> entitiesToAdd = new ArrayList<Entity>();
	
	Random random = Game.getRandomInstance();
	GameCamera camera = Game.getGameCameraInstance();
	
	public void tick() {
		for(Entity entity : entities) {
			if(entity.getX() >= camera.getViewArea().getMinimumX() && entity.getX() < camera.getViewArea().getMaximumX())
				entity.tick(entities);
		}
	}
	
	public void render(Graphics g) {
		for(Entity entity : entities) {
			if(entity.getX() >= camera.getViewArea().getMinimumX() && entity.getX() < camera.getViewArea().getMaximumX())
				entity.render(g);
		}
	}
	
	public void addEntityToList(EntityList list, Entity entity) {
		switch(list) {
		case ADD:
			entitiesToAdd.add(entity);
			break;
		case REMOVE:
			entitiesToRemove.add(entity);
			break;
		}
	}
		
	public void addEntitiesToGame() {
		for(Entity entity : entitiesToAdd) {
			entities.add(entity);
		}
		entitiesToAdd.clear();
	}
	
	public void removeEntitiesFromGame() {
		for(Entity entity : entitiesToRemove) {
			entities.remove(entity);
		}
		entitiesToRemove.clear();
	}
	
	public void addEntity(Entity entity) {
		this.entities.add(entity);
	}
	
	public void removeEntity(Entity entity) {
		this.entities.remove(entity);
	}
	
	public void checkCollision(Entity e, LinkedList<Entity> entities) {
		float height = e.getHeight();
		float width = e.getWidth();
		for(Entity entity : entities) {
			if(entity.getX() >= camera.getViewArea().getMinimumX() && entity.getX() < camera.getViewArea().getMaximumX()) {
				if(entity instanceof Block) {
					if(e.getBoundsTop().intersects(entity.getBounds())) {
						if(entity instanceof Bound || entity instanceof Dirt || entity instanceof Grass ||
								!(e instanceof Coin) && entity instanceof CoinBox || entity instanceof MissileLauncher) {
							e.setY(entity.getY() + height / 3);
							e.setVelocityY(0);
							if(entity instanceof CoinBox && e instanceof Character) {
								CoinBox coinbox = (CoinBox)entity;
								if(coinbox.hasCoinsLeft()) {
									Coin coin = new Coin(coinbox.getX() + (coinbox.getWidth() / 2) - Item.WIDTH / 2, coinbox.getY() - Item.HEIGHT + (Item.HEIGHT / 2), Item.WIDTH, Item.HEIGHT, null, 0.4f, Coin.NORMAL_RATE, false);
									coin.setVelocityX(0.8f);
									coin.setVelocityY(-9f);
									entitiesToAdd.add(coin);
									coinbox.removeCoin();
								} else {
									entitiesToRemove.add(coinbox);
								}
							} else if(e instanceof Missile && entity instanceof Block && !(entity instanceof MissileLauncher)) entitiesToRemove.add(e);
						} else if(entity instanceof CheckPoint) {
							e.setSpawnpoint(entity.getSpawnpoint());
						} else if(entity instanceof Sand && e instanceof Character) {
							e.setY(entity.getY() + height / 3);
						}
					}
					//Bottom Collision
					if(e.getBottomBounds().intersects(entity.getBounds())) {
						if(entity instanceof Bound || entity instanceof Dirt || entity instanceof Grass || 
								!(e instanceof Coin) && entity instanceof CoinBox || 
								!(e instanceof Character) && !(e instanceof Sand) && entity instanceof Sand ||
								entity instanceof MissileLauncher) {
							e.setY(entity.getY() - height);
							e.setVelocityY(0);
							e.setFalling(false);
							e.setJumping(false);
						} else if(entity instanceof CheckPoint) {
							e.setSpawnpoint(entity.getSpawnpoint());
						}
						else if(e instanceof Character && entity instanceof Sand) {
							e.setY(entity.getY() - height);
							e.setVelocityY(0);
							e.setFalling(false);
							e.setJumping(false);
							entity.setFalling(true);
						} else if (e instanceof Sand && entity instanceof Sand && !e.equals(entity)) {
							if(!entity.isFalling()) {
								entity.setFalling(true);
								e.setY(entity.getY() - height);
								e.setVelocityY(0);
								e.setFalling(false);
							}
						}
					} else {
						if(!(e instanceof Sand)) {
							e.setFalling(true);
						}
					}
					//Right Collision
					if(e.getBoundsRight().intersects(entity.getBounds())) {
						if(entity instanceof Bound || entity instanceof Dirt || entity instanceof Grass || 
								!(e instanceof Coin) && entity instanceof CoinBox || entity instanceof MissileLauncher) {
							e.setVelocityX(0);
							e.setX(entity.getX() - width);
						} else if(entity instanceof CheckPoint) {
							e.setSpawnpoint(entity.getSpawnpoint());
						} else if(e instanceof Character && entity instanceof Sand) {
							e.setX(entity.getX() - width);
						}
					}
					//Left Collision
					if(e.getBoundsLeft().intersects(entity.getBounds())) {
						if(entity instanceof Bound || entity instanceof Dirt || entity instanceof Grass || 
								!(e instanceof Coin) && entity instanceof CoinBox || entity instanceof MissileLauncher) {
							e.setVelocityX(0);
							e.setX(entity.getX() + (width / 2) + (width / 6));
						} else if(entity instanceof CheckPoint) {
							e.setSpawnpoint(entity.getSpawnpoint());
						} else if(e instanceof Character && entity instanceof Sand) {
							e.setX(entity.getX() + (width / 2) + (width / 6));
						}
					}
				} else if(entity instanceof Item && e instanceof Character) {
					if(entity instanceof Coin) {
						Coin coin = (Coin)entity;
						if(e.getBounds().intersects(coin.getBounds())) {
							if(!entitiesToRemove.contains(coin)) {
								entitiesToRemove.add(coin);
							}
						}
					}
				}
			}
		}
	}
	
	public Character getCharacter()  {
		Character character = null;
		for(Entity entity : entities) {
			if(entity.getX() >= camera.getViewArea().getMinimumX() && entity.getX() < camera.getViewArea().getMaximumX()) {
				if(entity instanceof Character) {
					character = (Character)entity;
					break;
				}
			}
		}
		return character;
	}
		
	public void preventGlitchingOutOfBounds(Character character) {
		if(character.getY() + character.getHeight() > Game.HEIGHT + character.getHeight()) {
			SpawnPoint spawnpoint = character.getSpawnpoint();
			character.setY(spawnpoint.getY());
			character.setX(spawnpoint.getX());
		}
	}
}
